package com.android.openapp.ui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.android.openapp.data.Place;
import com.android.openapp.services.Controller;
import com.android.openapp.services.Controller.ControllerBinder;
import com.android.openapp.R;
import com.google.android.maps.MapView;
import com.socrata.util.Variables;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.widget.TabHost;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;

/**
 * Usando le librerie support.v4.googlemaps (hackate) la classe FragmentActivity
 * estende MapActivity. e' quindi possibile usare una MapView all'interno di un Fragment.
 * @author Simone Panza
 * date 2012_08_28
 */
public class MainActivity extends FragmentActivity{

	public static String TAG = "OpenApp";
	
	public static final int PLACES_FRAGMENT = 0;
	public static final int MAP_FRAGMENT = 1;
	public static final int SETTINGS_FRAGMENT = 2;
	
	public static String PLACES_FRAGMENT_ID = "interest_places";
	public static String MAP_FRAGMENT_ID = "map";
	public static String SETTINGS_FRAGMENT_ID = "settings";
	
	public static String VIEW_MAP_TAB = "VIEW MAP TAB";
	
	TabHost mTabHost;
	TabManager mTabManager;
	
	ControllerBinder mBinder;
	ProgressDialog pd;
	ConnectivityManager mConnManager;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        createTabView();
        
        //binding al Controller (service)
        Intent i = new Intent(this, Controller.class);
        bindService(i, conn, Context.BIND_AUTO_CREATE);
        
        initializeMapView();
        
        handleIntent(getIntent()); //per gestire la ricezione di un Intent di tipo ACTION_SEARCH
    }
    
    /**
     * Quando viene effettuata una ricerca, viene mandato
     * un Intent alla MainActivity
     */
    @Override
    public void onNewIntent(Intent intent) {
    	setIntent(intent);
    	handleIntent(intent);
    }
    
    /**
     * Gestione degli Intent di ricerca
     * @param intent
     */
    private void handleIntent(Intent intent){
    	if (intent.getAction().equals(Intent.ACTION_SEARCH)) {
			//passo sempre al tab della lista
    		mTabHost.setCurrentTab(PLACES_FRAGMENT);
    		
    		String query = intent.getStringExtra(SearchManager.QUERY);
			Log.v(TAG, "search intent received: "+query);
			
			mBinder.searchForPlaces(query);
			
			//TODO aspetto il risultato o lo metto nel BroadcastReceiver?
			//se sincrono
			mCurrentFragment.onSearchCompleted();
		}
    }
    
    protected void createTabView(){
    	// set up tabs
        mTabHost = (TabHost) findViewById(android.R.id.tabhost);
        mTabHost.setup();
        
        mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent);
        
        Resources res = getResources();
        
        //add tabs
        mTabManager.addTab(mTabHost.newTabSpec(PLACES_FRAGMENT_ID).
        		setIndicator("", res.getDrawable(R.drawable.ic_menu_myplaces)),
        		PlacesListFragment.class, null);
        mTabManager.addTab(mTabHost.newTabSpec(MAP_FRAGMENT_ID).
        		setIndicator("", res.getDrawable(R.drawable.ic_menu_mapmode)),
        		MapFragment.class,null);
        mTabManager.addTab(mTabHost.newTabSpec(SETTINGS_FRAGMENT_ID).
        		setIndicator("", res.getDrawable(R.drawable.ic_menu_preferences)),
        		SettingsFragment.class,null);
    }
    
    protected void onDestroy() {
    	super.onDestroy();
    	unbindService(conn);
    }
    
    @Override
    protected void onStart() {
    	super.onStart();
    	//register receivers
    	IntentFilter filter;
		filter = new IntentFilter(Variables.DOWNLOAD_FINISHED);
		registerReceiver(mServiceReceiver, filter);
		filter = new IntentFilter(VIEW_MAP_TAB);
		registerReceiver(mServiceReceiver, filter);
		filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
		registerReceiver(mServiceReceiver, filter);
    }
    
    @Override
    protected void onStop() {
    	super.onStop();
    	unregisterReceiver(mServiceReceiver);
    }
   
    public void onBackPressed() {
    
    	 AlertDialog.Builder builder = new AlertDialog.Builder(this);
         builder.setMessage("Sei sicuro di volere uscire? ")
                .setCancelable(false)
                .setPositiveButton("Si", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    	finish();
              
                    }
                })
                .setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                         dialog.cancel();
                    }
                });
         AlertDialog alert = builder.create();
         alert.show();
         
         
    };
    
    
    /**
     * Oggetto di tipo ServiceConnection che gestisce il binding/unbinding al servizio Controller
     */
    ServiceConnection conn = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mBinder = (ControllerBinder) service;
			mBinder.setActivity(MainActivity.this);
			//avverto i fragment che ho fatto il binding
			mCurrentFragment.onBind(mBinder);
		}
	};
	
	/**
	 * Gestione dei messaggi (Intent) in arrivo dal Service
	 */
	BroadcastReceiver mServiceReceiver = new BroadcastReceiver() {
		
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			Log.v(TAG,action);
			if (action.equals(Variables.DOWNLOAD_FINISHED)) {
				switch(intent.getExtras().getInt(Variables.DOWNLOAD_RESULT)){
				case Variables.NO_ERROR:
					Log.d("DOWNLOAD FINISHED", "DOWNLOAD SUCCESFULLY COMPLETED!");
					mCurrentFragment.onDataReceived();
					break;
				case Variables.DOWNLOAD_ERROR:
					Log.d("DOWNLOAD FINISHED", "DOWNLOAD ERROR!");
					//TODO anche in caso di errore chiamo mCurrentFragment.onDataReceived(); ?
					break;
				}
			}
			else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)){
				if(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY)){
					Intent i = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
					//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					startActivity(i);
					Utils.showToast(context, "Please enable network connection");
				}
			}
			else if (action.equals(VIEW_MAP_TAB)){
				mTabHost.setCurrentTab(MAP_FRAGMENT);
				int index = intent.getExtras().getInt("index");
				mCurrentFragment.onLocationReceived(index);
			}
		}
	};
		
	FragmentInteract mCurrentFragment;
	public void setCurrentFragment(FragmentInteract fragment){
		mCurrentFragment = fragment;
	}
    
	/**
	 * Premendo il tasto Option compare il menu:
	 * ma abbiamo gi� il tab opzioni
	 */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    
    /*
     * Methods for MapActivity
     * Using the hacked support library v4: FragmentActivity extends MapActivity
     * so we can show a MapView into a Fragment.
     */
    
    @Override
    protected boolean isRouteDisplayed() {
    	return false;
    }
    
	View mMapViewContainer;
	MapView mMapView;
    
    private void initializeMapView(){
    	mMapViewContainer = LayoutInflater.from(this).inflate(R.layout.maplayout, null);
    	mMapView = (MapView) mMapViewContainer.findViewById(R.id.mapview);
    }
    
    /**
     * This is a helper class that implements a generic mechanism for
     * associating fragments with the tabs in a tab host.  It relies on a
     * trick.  Normally a tab host has a simple API for supplying a View or
     * Intent that each tab will show.  This is not sufficient for switching
     * between fragments.  So instead we make the content part of the tab host
     * 0dp high (it is not shown) and the TabManager supplies its own dummy
     * view to show as the tab content.  It listens to changes in tabs, and takes
     * care of switch to the correct fragment shown in a separate content area
     * whenever the selected tab changes.
     */
    public static class TabManager implements TabHost.OnTabChangeListener {
        private final FragmentActivity mActivity;
        private final TabHost mTabHost;
        private final int mContainerId;
        private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>();
        TabInfo mLastTab;

        static final class TabInfo {
            private final String tag;
            private final Class<?> clss;
            private final Bundle args;
            private Fragment fragment;

            TabInfo(String _tag, Class<?> _class, Bundle _args) {
                tag = _tag;
                clss = _class;
                args = _args;
            }
        }

        static class DummyTabFactory implements TabHost.TabContentFactory {
            private final Context mContext;

            public DummyTabFactory(Context context) {
                mContext = context;
            }

            @Override
            public View createTabContent(String tag) {
                View v = new View(mContext);
                v.setMinimumWidth(0);
                v.setMinimumHeight(0);
                return v;
            }
        }

        public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
            mActivity = activity;
            mTabHost = tabHost;
            mContainerId = containerId;
            mTabHost.setOnTabChangedListener(this);
        }

        public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
            tabSpec.setContent(new DummyTabFactory(mActivity));
            String tag = tabSpec.getTag();

            TabInfo info = new TabInfo(tag, clss, args);

            // Check to see if we already have a fragment for this tab, probably
            // from a previously saved state.  If so, deactivate it, because our
            // initial state is that a tab isn't shown.
            info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
            if (info.fragment != null && !info.fragment.isDetached()) {
                FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
                ft.detach(info.fragment);
                ft.commit();
            }

            mTabs.put(tag, info);
            mTabHost.addTab(tabSpec);
        }

        @Override
        public void onTabChanged(String tabId) {
            TabInfo newTab = mTabs.get(tabId);
            if (mLastTab != newTab) {
                FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
                if (mLastTab != null) {
                    if (mLastTab.fragment != null) {
                        ft.detach(mLastTab.fragment);
                    }
                }
                if (newTab != null) {
                    if (newTab.fragment == null) {
                        newTab.fragment = Fragment.instantiate(mActivity,
                                newTab.clss.getName(), newTab.args);
                        ft.add(mContainerId, newTab.fragment, newTab.tag);
                    } else {
                        ft.attach(newTab.fragment);
                    }
                }

                mLastTab = newTab;
                ft.commit();
                mActivity.getSupportFragmentManager().executePendingTransactions();
            }
        }
    }
}